/*
 * vm.h
 *
 * Group: Fantastic Five
 * Date: 4/29/08
 *
 * Description: headers for vm.c - VM instructions
 */

/* 
 * Runs error free program, stored in il
 */
void vm_run_program(FILE *out, FILE *in, FILE *err, struct instr_list *il);

/* 
 * Implements the CPY Ra Rb instruction
 * Ra = source      Rb = destination
 */
void CPY_Ra_Rb(enum reg Ra, enum reg Rb);

/* 
 * Implements the CLR Ra instruction
 * Sets value in Ra equal to zero and changes type to INTEGER
 */
void CLR_Ra(enum reg Ra);

/* 
 * Implements the MOV Ra struct instruction 
 * Puts new_val into Ra
 */
void MOV_Ra_struct(enum reg Ra, struct regstr new_val);

/* 
 * Implements the CMP Ra Rb instruction
 * Stores result in comparison register, RC
 * 0 if equal, 1 if Ra > Rb, -1 if Ra < Rb
 */
void CMP_Ra_Rb(enum reg Ra, enum reg Rb);

/* 
 * Implements the INC Ra instruction
 * Adds 1 to Ra, doesn't care if Ra is float or int
 */
void INC_Ra(enum reg Ra);

/* 
 * Implements the DEC Ra instruction
 * Subtracts 1 from Ra, doesn't care if Ra is float or int
 */
void DEC_Ra(enum reg Ra);

/* 
 * Implements the PUT Ra instruction
 * Outputs the contents of Ra to stdout
 */
void PUT_Ra(enum reg Ra);

/* 
 * Implements the PTC char instruction
 * Outputs the given character to stdout
 */
void PTC_char(char ch);

/*
 * ADD instruction for Register/Register parameters.
 * Adds two registers and places the result in the first register.
 */
void ADD_Ra_Rb(enum reg Ra, enum reg Rb);

/*
 * ADD instruction for Register/Struct parameters.
 * Adds a register and a numerical value and places the result in the register.
 */
void ADD_Ra_struct(enum reg Ra, struct regstr newval);

/*
 * SUB instruction for Register/Register inputs.
 * Subtracts two registers and places the result in the first register.
 */
void SUB_Ra_Rb(enum reg Ra, enum reg Rb);

/*
 * SUB instruction for Register/Struct parameters.
 * Subtracts a numerical value from a register and places the result in the register.
 */
void SUB_Ra_struct(enum reg Ra, struct regstr newval);

/*
 * SUB instruction for Struct/Register parameters.
 * Subtracts a register from a numerical value and places the result in the register.
 */
void SUB_struct_Ra(struct regstr newval, enum reg Ra);

/* 
 * MUL instruction for two registers
 * Multiplies two registers and stores the value in the first
 */
void MUL_Ra_Rb(enum reg Ra, enum reg Rb);

/* 
 * MUL instruction for register and input value
 * Multiplies reg*struct and stores the value in the register
 */
void MUL_Ra_struct(enum reg Ra, struct regstr newval);

/* 
 * DIV instruction for two registers
 * Divides two registers and stores the value in the first
 */
void DIV_Ra_Rb(enum reg Ra, enum reg Rb);

/* 
 * DIV instruction for register and input value
 * Divides reg/struct and stores the value in the register
 */
void DIV_Ra_struct(enum reg Ra, struct regstr newval);

/* 
 * DIV instruction for register and input value
 * Divides struct/reg and stores the value in the register
 */
void DIV_struct_Ra(struct regstr newval, enum reg Ra);

/*
 * JZ instruction.
 * Jumps to the specified line number if register == 0.
 * Otherwise, just advance to the next line.
 */
struct instr *JZ_Ra_line(enum reg Ra, int linenum, struct instr *curline);

/*
 * JNZ instruction.
 * Jumps to the specified line number if register != 0.
 * Otherwise, just advance to the next line.
 */
struct instr *JNZ_Ra_line(enum reg Ra, int linenum, struct instr *curline);

/*
 * JMP instruction.
 * Jumps to the specified line number, if possible.
 * Otherwise, the line number to jump to is out of range.  Program ends.
 */
struct instr *JMP_line(int linenum, struct instr *curline);

/*
 * Returns a pointer to the node in instruction list that should be the next implemented line.
 * If the register is greater than zero it jumps to the given line, otherwise it jumps to the next line.
 * If it does not jump it returns the next line, if it does jump it returns the line that you jumped to.
 * If the line to jump to is past the end of the list, then it returns the last in the list.
 * 
 * Specifically then, if your VM code moves to the next line at the end of every iteration, you 
 * will need to be sure to take into account that these jump functions do that already. 
 * If you can think of a better way to do a jump by all means change it.
 */
struct instr * JGT_Ra_line(enum reg Ra, int linenum, struct instr * curline);

/* 
 * Returns a pointer to the node in the instruction list, if the register is less than zero, that is the next
 * line that needs to be implemented.
 */
struct instr * JLT_Ra_line(enum reg Ra, int linenum, struct instr * curline);

/*
 * GET instruction.
 * Prompts the User for input.  They must enter a number or it will blow up.
 */
void GET_Ra(enum reg Ra, FILE *in, FILE *out, FILE *err);
